// 资源预加载工具
export interface PreloadOptions {
    priority?: 'high' | 'low'
    as?: 'script' | 'style' | 'image' | 'font' | 'fetch'
    crossOrigin?: 'anonymous' | 'use-credentials'
    type?: string
}

export class ResourcePreloader {
    private static instance: ResourcePreloader
    private preloadedResources = new Set<string>()
    private preloadQueue: Array<{ url: string; options: PreloadOptions }> = []
    private isProcessing = false

    private constructor() { }

    public static getInstance(): ResourcePreloader {
        if (!ResourcePreloader.instance) {
            ResourcePreloader.instance = new ResourcePreloader()
        }
        return ResourcePreloader.instance
    }

    // 预加载单个资源
    public preload(url: string, options: PreloadOptions = {}): Promise<void> {
        if (this.preloadedResources.has(url)) {
            return Promise.resolve()
        }

        return new Promise((resolve, reject) => {
            if (typeof window === 'undefined') {
                resolve()
                return
            }

            const link = document.createElement('link')
            link.rel = 'preload'
            link.href = url

            if (options.as) link.as = options.as
            if (options.crossOrigin) link.crossOrigin = options.crossOrigin
            if (options.type) link.type = options.type

            link.onload = () => {
                this.preloadedResources.add(url)
                resolve()
            }

            link.onerror = () => {
                reject(new Error(`Failed to preload resource: ${url}`))
            }

            document.head.appendChild(link)
        })
    }

    // 批量预加载
    public async preloadBatch(resources: Array<{ url: string; options?: PreloadOptions }>): Promise<void> {
        const promises = resources.map(({ url, options = {} }) =>
            this.preload(url, options).catch(error => {
                console.warn(`Failed to preload ${url}:`, error)
                return null
            })
        )

        await Promise.allSettled(promises)
    }

    // 添加到预加载队列
    public queuePreload(url: string, options: PreloadOptions = {}): void {
        if (!this.preloadedResources.has(url)) {
            this.preloadQueue.push({ url, options })
            this.processQueue()
        }
    }

    // 处理预加载队列
    private async processQueue(): Promise<void> {
        if (this.isProcessing || this.preloadQueue.length === 0) {
            return
        }

        this.isProcessing = true

        // 按优先级排序
        this.preloadQueue.sort((a, b) => {
            const priorityA = a.options.priority === 'high' ? 1 : 0
            const priorityB = b.options.priority === 'high' ? 1 : 0
            return priorityB - priorityA
        })

        // 批量处理（每次最多5个）
        while (this.preloadQueue.length > 0) {
            const batch = this.preloadQueue.splice(0, 5)
            await this.preloadBatch(batch)

            // 给浏览器一些时间处理其他任务
            await new Promise(resolve => setTimeout(resolve, 10))
        }

        this.isProcessing = false
    }

    // 预加载关键CSS
    public preloadCriticalCSS(urls: string[]): Promise<void> {
        return this.preloadBatch(
            urls.map(url => ({
                url,
                options: { as: 'style', priority: 'high' }
            }))
        )
    }

    // 预加载字体
    public preloadFonts(urls: string[]): Promise<void> {
        return this.preloadBatch(
            urls.map(url => ({
                url,
                options: { as: 'font', crossOrigin: 'anonymous', priority: 'high' }
            }))
        )
    }

    // 预加载图片
    public preloadImages(urls: string[]): Promise<void> {
        return this.preloadBatch(
            urls.map(url => ({
                url,
                options: { as: 'image', priority: 'low' }
            }))
        )
    }

    // 预加载API数据
    public async preloadApiData(urls: string[]): Promise<void> {
        const promises = urls.map(async url => {
            try {
                const response = await fetch(url)
                if (response.ok) {
                    // 数据已被浏览器缓存
                    this.preloadedResources.add(url)
                }
            } catch (error) {
                console.warn(`Failed to preload API data from ${url}:`, error)
            }
        })

        await Promise.allSettled(promises)
    }

    // 检查资源是否已预加载
    public isPreloaded(url: string): boolean {
        return this.preloadedResources.has(url)
    }

    // 清理预加载资源记录
    public clear(): void {
        this.preloadedResources.clear()
        this.preloadQueue = []
    }

    // 获取预加载统计
    public getStats() {
        return {
            preloadedCount: this.preloadedResources.size,
            queueLength: this.preloadQueue.length,
            isProcessing: this.isProcessing
        }
    }
}

// 全局预加载器实例
export const preloader = ResourcePreloader.getInstance()

// React Hook for resource preloading
export function usePreloader() {
    const preloadResource = (url: string, options?: PreloadOptions) => {
        return preloader.preload(url, options)
    }

    const preloadBatch = (resources: Array<{ url: string; options?: PreloadOptions }>) => {
        return preloader.preloadBatch(resources)
    }

    const queuePreload = (url: string, options?: PreloadOptions) => {
        preloader.queuePreload(url, options)
    }

    const isPreloaded = (url: string) => {
        return preloader.isPreloaded(url)
    }

    return {
        preloadResource,
        preloadBatch,
        queuePreload,
        isPreloaded
    }
}

// 数据预加载策略枚举
export enum DataPreloadStrategy {
    IMMEDIATE = 'immediate',
    ON_HOVER = 'on_hover',
    ON_VIEWPORT = 'on_viewport',
    ON_IDLE = 'on_idle',
    PREDICTIVE = 'predictive'
}

// 数据预加载任务接口
export interface DataPreloadTask {
    key: string
    priority: number
    strategy: DataPreloadStrategy
    loader: () => Promise<any>
    dependencies?: string[]
    estimatedSize?: number
    timeout?: number
}

// 数据预加载器类
export class DataPreloader {
    private static instance: DataPreloader
    private cache = new Map<string, { data: any; timestamp: number; ttl: number }>()
    private preloadQueue: Map<string, Promise<any>> = new Map()
    private priorityQueue: DataPreloadTask[] = []
    private isExecuting = false
    private intersectionObserver?: IntersectionObserver
    private idleCallback?: number
    private maxCacheSize = 100
    private defaultTTL = 15 * 60 * 1000 // 15分钟

    private constructor() {
        this.initializeObservers()
    }

    public static getInstance(): DataPreloader {
        if (!DataPreloader.instance) {
            DataPreloader.instance = new DataPreloader()
        }
        return DataPreloader.instance
    }

    // 初始化观察器
    private initializeObservers(): void {
        if (typeof window === 'undefined') return

        // 初始化 Intersection Observer 用于视口预加载
        if ('IntersectionObserver' in window) {
            this.intersectionObserver = new IntersectionObserver(
                (entries) => {
                    entries.forEach(entry => {
                        if (entry.isIntersecting) {
                            const key = entry.target.getAttribute('data-preload-key')
                            if (key) {
                                this.executeTaskByKey(key)
                            }
                        }
                    })
                },
                { rootMargin: '50px' }
            )
        }

        // 使用 requestIdleCallback 进行空闲时预加载
        if ('requestIdleCallback' in window) {
            this.scheduleIdlePreload()
        }
    }

    // 添加预加载任务
    addPreloadTask(task: DataPreloadTask): void {
        if (this.has(task.key) || this.preloadQueue.has(task.key)) {
            return // 已经缓存或正在加载
        }

        // 检查依赖项
        if (task.dependencies) {
            const missingDeps = task.dependencies.filter(dep => !this.has(dep))
            if (missingDeps.length > 0) {
                console.warn(`Task ${task.key} has missing dependencies:`, missingDeps)
            }
        }

        this.priorityQueue.push(task)
        this.priorityQueue.sort((a, b) => b.priority - a.priority) // 按优先级排序

        // 根据策略执行
        switch (task.strategy) {
            case DataPreloadStrategy.IMMEDIATE:
                this.executeTask(task)
                break
            case DataPreloadStrategy.ON_IDLE:
                this.scheduleIdlePreload()
                break
            // ON_HOVER 和 ON_VIEWPORT 由外部触发
        }
    }

    // 批量添加预加载任务
    addPreloadTasks(tasks: DataPreloadTask[]): void {
        tasks.forEach(task => this.addPreloadTask(task))
    }

    // 执行预加载
    async executePreload(maxConcurrent = 3): Promise<void> {
        if (this.isExecuting) return
        this.isExecuting = true

        try {
            const executing: Promise<any>[] = []
            const immediateTasks = this.priorityQueue.filter(task =>
                task.strategy === DataPreloadStrategy.IMMEDIATE
            )

            while (immediateTasks.length > 0 || executing.length > 0) {
                // 启动新任务直到达到最大并发数
                while (executing.length < maxConcurrent && immediateTasks.length > 0) {
                    const task = immediateTasks.shift()!
                    const promise = this.executeTask(task)
                    executing.push(promise)
                }

                // 等待至少一个任务完成
                if (executing.length > 0) {
                    await Promise.race(executing)
                    // 移除已完成的任务
                    for (let i = executing.length - 1; i >= 0; i--) {
                        try {
                            const result = await Promise.race([
                                executing[i],
                                new Promise(resolve => setTimeout(() => resolve('pending'), 0))
                            ])
                            if (result !== 'pending') {
                                executing.splice(i, 1)
                            }
                        } catch {
                            executing.splice(i, 1)
                        }
                    }
                }
            }
        } finally {
            this.isExecuting = false
        }
    }

    // 执行单个任务
    private async executeTask(task: DataPreloadTask): Promise<any> {
        return this.loadAndCache(task.key, task.loader, task.timeout)
    }

    // 根据key执行任务
    public async executeTaskByKey(key: string): Promise<any> {
        const task = this.priorityQueue.find(t => t.key === key)
        if (task) {
            return this.executeTask(task)
        }
    }

    // 加载并缓存数据
    private async loadAndCache(
        key: string,
        loader: () => Promise<any>,
        timeout = 10000
    ): Promise<any> {
        if (this.preloadQueue.has(key)) {
            return this.preloadQueue.get(key)
        }

        const timeoutPromise = new Promise((_, reject) => {
            setTimeout(() => reject(new Error(`Preload timeout for ${key}`)), timeout)
        })

        const promise = Promise.race([loader(), timeoutPromise])
            .then(data => {
                this.set(key, data)
                this.preloadQueue.delete(key)
                // 从队列中移除已完成的任务
                this.priorityQueue = this.priorityQueue.filter(t => t.key !== key)
                return data
            })
            .catch(error => {
                this.preloadQueue.delete(key)
                console.warn(`Preload failed for ${key}:`, error)
                throw error
            })

        this.preloadQueue.set(key, promise)
        return promise
    }

    // 调度空闲时预加载
    private scheduleIdlePreload(): void {
        if (this.idleCallback) {
            cancelIdleCallback(this.idleCallback)
        }

        this.idleCallback = requestIdleCallback((deadline) => {
            const idleTasks = this.priorityQueue.filter(task =>
                task.strategy === DataPreloadStrategy.ON_IDLE
            )

            while (deadline.timeRemaining() > 0 && idleTasks.length > 0) {
                const task = idleTasks.shift()!
                this.executeTask(task)
            }

            // 如果还有任务，继续调度
            if (idleTasks.length > 0) {
                this.scheduleIdlePreload()
            }
        })
    }

    // 设置缓存
    private set(key: string, data: any, ttl = this.defaultTTL): void {
        // 如果缓存已满，删除最旧的项
        if (this.cache.size >= this.maxCacheSize) {
            const oldestKey = this.cache.keys().next().value
            if (oldestKey) {
                this.cache.delete(oldestKey)
            }
        }

        this.cache.set(key, {
            data,
            timestamp: Date.now(),
            ttl
        })
    }

    // 获取缓存数据
    get(key: string): any | null {
        const item = this.cache.get(key)
        if (!item) return null

        // 检查是否过期
        if (Date.now() - item.timestamp > item.ttl) {
            this.cache.delete(key)
            return null
        }

        return item.data
    }

    // 检查是否有缓存
    has(key: string): boolean {
        return this.get(key) !== null
    }

    // 注册视口预加载元素
    observeElement(element: Element, preloadKey: string): void {
        if (this.intersectionObserver) {
            element.setAttribute('data-preload-key', preloadKey)
            this.intersectionObserver.observe(element)
        }
    }

    // 取消观察元素
    unobserveElement(element: Element): void {
        if (this.intersectionObserver) {
            this.intersectionObserver.unobserve(element)
        }
    }

    // 获取预加载统计
    getStats() {
        return {
            cacheSize: this.cache.size,
            maxCacheSize: this.maxCacheSize,
            queueLength: this.priorityQueue.length,
            activeLoads: this.preloadQueue.size,
            isExecuting: this.isExecuting
        }
    }

    // 清理预加载器
    clear(): void {
        this.cache.clear()
        this.preloadQueue.clear()
        this.priorityQueue = []

        if (this.idleCallback) {
            cancelIdleCallback(this.idleCallback)
            this.idleCallback = undefined
        }
    }

    // 销毁预加载器
    destroy(): void {
        this.clear()

        if (this.intersectionObserver) {
            this.intersectionObserver.disconnect()
            this.intersectionObserver = undefined
        }
    }
}

// 智能预加载策略
export class SmartPreloader {
    private static instance: SmartPreloader
    private userBehaviorData = new Map<string, number>()
    private preloader = ResourcePreloader.getInstance()
    private dataPreloader = DataPreloader.getInstance()
    private networkInfo: any = null

    private constructor() {
        this.initializeBehaviorTracking()
        this.initializeNetworkMonitoring()
    }

    public static getInstance(): SmartPreloader {
        if (!SmartPreloader.instance) {
            SmartPreloader.instance = new SmartPreloader()
        }
        return SmartPreloader.instance
    }

    // 初始化网络监控
    private initializeNetworkMonitoring(): void {
        if (typeof window === 'undefined') return

        // 监控网络状态
        if ('connection' in navigator) {
            this.networkInfo = (navigator as any).connection

            this.networkInfo.addEventListener('change', () => {
                this.adjustPreloadStrategy()
            })
        }
    }

    // 根据网络状况调整预加载策略
    private adjustPreloadStrategy(): void {
        if (!this.networkInfo) return

        const { effectiveType, downlink, saveData } = this.networkInfo

        // 如果用户启用了数据节省模式，减少预加载
        if (saveData) {
            console.log('Data saver mode detected, reducing preload activity')
            return
        }

        // 根据网络速度调整预加载
        if (effectiveType === '4g' && downlink > 2) {
            // 高速网络，积极预加载
            this.enableAggressivePreload()
        } else if (effectiveType === '3g' || downlink < 1) {
            // 慢速网络，保守预加载
            this.enableConservativePreload()
        }
    }

    // 启用积极预加载
    private enableAggressivePreload(): void {
        // 预加载更多资源
        const recommendations = this.getRecommendedPreloads()
        recommendations.slice(0, 15).forEach(url => {
            this.preloader.queuePreload(url, { as: 'fetch', priority: 'low' })
        })
    }

    // 启用保守预加载
    private enableConservativePreload(): void {
        // 只预加载高优先级资源
        const recommendations = this.getRecommendedPreloads()
        recommendations.slice(0, 5).forEach(url => {
            this.preloader.queuePreload(url, { as: 'fetch', priority: 'high' })
        })
    }

    // 初始化用户行为跟踪
    private initializeBehaviorTracking(): void {
        if (typeof window === 'undefined') return

        // 跟踪鼠标悬停
        document.addEventListener('mouseover', (event) => {
            const target = event.target as HTMLElement
            const link = target.closest('a[href]') as HTMLAnchorElement
            if (link) {
                this.recordBehavior(link.href)
                this.considerPreload(link.href)
            }

            // 检查数据预加载触发器
            const preloadKey = target.getAttribute('data-preload-key')
            if (preloadKey) {
                this.dataPreloader.executeTaskByKey(preloadKey)
            }
        })

        // 跟踪点击模式
        document.addEventListener('click', (event) => {
            const target = event.target as HTMLElement
            const link = target.closest('a[href]') as HTMLAnchorElement
            if (link) {
                this.recordBehavior(link.href, 3) // 点击权重更高
            }
        })
    }

    // 记录用户行为
    private recordBehavior(url: string, weight = 1): void {
        const current = this.userBehaviorData.get(url) || 0
        this.userBehaviorData.set(url, current + weight)
    }

    // 考虑是否预加载
    private considerPreload(url: string): void {
        const score = this.userBehaviorData.get(url) || 0

        // 如果用户对这个链接有足够的兴趣，就预加载
        if (score >= 2) {
            this.preloader.queuePreload(url, { as: 'fetch', priority: 'low' })
        }
    }

    // 获取推荐预加载的资源
    public getRecommendedPreloads(): string[] {
        const recommendations: Array<{ url: string; score: number }> = []

        for (const [url, score] of this.userBehaviorData) {
            if (score >= 2 && !this.preloader.isPreloaded(url)) {
                recommendations.push({ url, score })
            }
        }

        return recommendations
            .sort((a, b) => b.score - a.score)
            .slice(0, 10) // 最多推荐10个
            .map(item => item.url)
    }

    // 预测性预加载
    public predictivePreload(currentPath: string): void {
        // 基于当前路径预测用户可能访问的下一个页面
        const predictions = this.getPredictions(currentPath)

        predictions.forEach(prediction => {
            this.preloader.queuePreload(prediction.url, {
                as: 'fetch',
                priority: prediction.confidence > 0.7 ? 'high' : 'low'
            })
        })
    }

    // 获取路径预测
    private getPredictions(currentPath: string): Array<{ url: string; confidence: number }> {
        // 简单的预测逻辑，实际应用中可以使用机器学习模型
        const predictions: Array<{ url: string; confidence: number }> = []

        if (currentPath === '/') {
            predictions.push(
                { url: '/dataset/1', confidence: 0.8 },
                { url: '/dataset/2', confidence: 0.6 }
            )
        } else if (currentPath.startsWith('/dataset/')) {
            const datasetId = currentPath.split('/')[2]
            predictions.push(
                { url: `/task/${datasetId}/1`, confidence: 0.7 },
                { url: `/task/${datasetId}/2`, confidence: 0.5 }
            )
        }

        return predictions
    }

    // 清理行为数据
    public clearBehaviorData(): void {
        this.userBehaviorData.clear()
    }

    // 获取网络信息
    public getNetworkInfo() {
        return this.networkInfo ? {
            effectiveType: this.networkInfo.effectiveType,
            downlink: this.networkInfo.downlink,
            rtt: this.networkInfo.rtt,
            saveData: this.networkInfo.saveData
        } : null
    }
}

export const smartPreloader = SmartPreloader.getInstance()
export const dataPreloader = DataPreloader.getInstance()